# -*- coding: utf-8 -*-
import functools
import logging

from .tools import lru_cache_ttl

DATEFMT = '%Y-%m-%d %H:%M:%S'


class ColoredStreamHandler(logging.StreamHandler):
    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = ['\033[0;{}m'.format(i) for i in range(30, 38)]
    RESET = '\033[0m'

    def format(self, record):
        levelno = record.levelno
        if levelno == 10:
            message = '%(message)s'
        elif levelno == 20:
            message = '{}%(message)s{}'.format(self.GREEN, self.RESET)
        elif levelno == 30:
            message = '{}%(message)s{}'.format(self.YELLOW, self.RESET)
        else:
            message = '{}%(message)s{}'.format(self.RED, self.RESET)
        fmt = '%(asctime)s [%(levelname).1s] [%(name)s %(filename)s %(funcName)s %(lineno)d] |{} {}'.format(
            self.RESET, message
        )
        fmter = logging.Formatter(fmt=fmt)
        return fmter.format(record)

    def emit(self, record):
        try:
            msg = self.format(record)
            stream = self.stream
            stream.write(msg + self.terminator)
            self.flush()
        except RecursionError:  # See issue 36272
            raise
        except Exception:
            self.handleError(record)


class hdict(dict):
    def __hash__(self):
        return True


class CacheLoggerAdapter(logging.LoggerAdapter):

    def __init__(self, logger, extra):
        self.logger = logger
        self.extra = hdict(extra)

    @functools.lru_cache()
    def cache(self, func, ttl: int = 60, maxsize: int = 128, typed: bool = False):
        return lru_cache_ttl(ttl, maxsize, typed)(func)

    def log(self, level, msg, *args, ttl: int = 3, maxsize: int = 128, typed: bool = False, **kwargs):
        if self.isEnabledFor(level):
            msg, kwargs = self.process(msg, kwargs)
            self.cache(self.logger.log, ttl, maxsize, typed)(level, msg, *args, **kwargs)
